<?php
/**
 * Created by PhpStorm.
 * User: zhangyajie
 * Date: 2020/11/11
 * Time: 18:10
 */
namespace  App\Utils;

use MQ\Model\TopicMessage;
use MQ\MQClient;

class MqConsumer
{

    private $client;
    private $producer;
    public $accessKeyId = 'LTAI4GFyQ2yRnTG4UKGXcUwq';
    public $accessSecret = 'bJ893KlddGsn7ZViGHTwqztjevubZn';
    public $instanceId = 'MQ_INST_50112006_BXYle0HK';
    public $host = 'http://50112006.mqrest.cn-beijing.aliyuncs.com';


    public function __construct()
    {
        $this->client = new MQClient($this->host, $this->accessKeyId, $this->accessSecret);

        // 所属的 Topic
        $topic = "test";
        // 您在控制台创建的 Consumer ID(Group ID)
        $groupId = "GID_TEST";
        // Topic所属实例ID，默认实例为空NULL
        $instanceId = $this->instanceId;

        $this->consumer = $this->client->getConsumer($instanceId, $topic, $groupId);
    }

    public function run()
    {

        $messages = $this->consumer->consumeMessage(
            1, // 一次最多消费3条(最多可设置为16条)
            3 // 长轮询时间3秒（最多可设置为30秒）
        );

//        var_dump($messages);

        // 处理业务逻辑
        $receiptHandles = array();
        foreach ($messages as $message) {
            $receiptHandles[] = $message->getReceiptHandle();
            printf("MessageID:%s TAG:%s BODY:%s \nPublishTime:%d, FirstConsumeTime:%d, \nConsumedTimes:%d, NextConsumeTime:%d,MessageKey:%s\n",
                $message->getMessageId(), $message->getMessageTag(), $message->getMessageBody(),
                $message->getPublishTime(), $message->getFirstConsumeTime(), $message->getConsumedTimes(), $message->getNextConsumeTime(),
                $message->getMessageKey());
            print_r($message->getProperties());
        }

        try {
            $this->consumer->ackMessage($receiptHandles);
        } catch (\Exception $e) {
            if ($e instanceof MQ\Exception\AckMessageException) {
                // 某些消息的句柄可能超时了会导致确认不成功
                printf("Ack Error, RequestId:%s\n", $e->getRequestId());
                foreach ($e->getAckMessageErrorItems() as $errorItem) {
                    printf("\tReceiptHandle:%s, ErrorCode:%s, ErrorMsg:%s\n", $errorItem->getReceiptHandle(), $errorItem->getErrorCode(), $errorItem->getErrorCode());
                }
            }
        }
        print "ack finish\n";



        die;

        // 在当前线程循环消费消息，建议是多开个几个线程并发消费消息
        while (True) {
            try {
                // 长轮询消费消息
                // 长轮询表示如果topic没有消息则请求会在服务端挂住3s，3s内如果有消息可以消费则立即返回
                $messages = $this->consumer->consumeMessage(
                    3, // 一次最多消费3条(最多可设置为16条)
                    3 // 长轮询时间3秒（最多可设置为30秒）
                );

                var_dump($messages);
            } catch (\Exception $e) {
                if ($e instanceof MQ\Exception\MessageNotExistException) {
                    // 没有消息可以消费，接着轮询
                    printf("No message, contine long polling!RequestId:%s\n", $e->getRequestId());
                    continue;
                }

                print_r($e->getMessage() . "\n");

                sleep(3);
                continue;
            }

            print "consume finish, messages:\n";

            // 处理业务逻辑
            $receiptHandles = array();
            foreach ($messages as $message) {
                $receiptHandles[] = $message->getReceiptHandle();
                printf("MessageID:%s TAG:%s BODY:%s \nPublishTime:%d, FirstConsumeTime:%d, \nConsumedTimes:%d, NextConsumeTime:%d,MessageKey:%s\n",
                    $message->getMessageId(), $message->getMessageTag(), $message->getMessageBody(),
                    $message->getPublishTime(), $message->getFirstConsumeTime(), $message->getConsumedTimes(), $message->getNextConsumeTime(),
                    $message->getMessageKey());
                print_r($message->getProperties());
            }

            // $message->getNextConsumeTime()前若不确认消息消费成功，则消息会重复消费
            // 消息句柄有时间戳，同一条消息每次消费拿到的都不一样
            print_r($receiptHandles);
            try {
                $this->consumer->ackMessage($receiptHandles);
            } catch (\Exception $e) {
                if ($e instanceof MQ\Exception\AckMessageException) {
                    // 某些消息的句柄可能超时了会导致确认不成功
                    printf("Ack Error, RequestId:%s\n", $e->getRequestId());
                    foreach ($e->getAckMessageErrorItems() as $errorItem) {
                        printf("\tReceiptHandle:%s, ErrorCode:%s, ErrorMsg:%s\n", $errorItem->getReceiptHandle(), $errorItem->getErrorCode(), $errorItem->getErrorCode());
                    }
                }
            }
            print "ack finish\n";


        }

    }


}
